package com.jl.slick.util.graphics;

import java.awt.Point;
import java.util.HashMap;
import java.util.Vector;

import org.newdawn.slick.BasicGame;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.SpriteSheet;

import com.jl.slick.objects.graphics.Level;

public class BackgroundEditor extends BasicGame //NEED TO SIMPLY PASS IMAGE OBJECT ACROSS..maybe
{
	private String tilesetfile, loadfile;
	private SpriteSheet tileset;
	private Image imagewithgrid, tiletopaint, loadedimage;
	int doOnce = 0, tilewidth, tileheight, filewidth, fileheight;
	private boolean lshift, lctrl, skey;
	HashMap<Point, Image> paintlist, tilestopaint; //TODO: NEED ANOTHER GROUP TILE HASHMAP TO LOOP THROUGH UPON CLICK AND ADD EACH TO THIS HASHMAP
	//HashMap<Point, FX> FX;
	Vector<Point> collidables;
	Point begin, end;
	//IDEA: divide into two hashmaps with threaded printing?
	public BackgroundEditor(String tilesetfile)
	{
		super("Background Editor"); //title
		this.tilesetfile = tilesetfile; //file name of spritesheet/tileset to use. 
		lshift = false;
		lctrl = false;
	}
	
	public void tilepaint(int x, int y)// single tile paint
	{
		tiletopaint = tileset.getSubImage(x, y); //currently selected tile from the TS. TS calls this so the BE knows which tile of the mutually loaded spritesheet to paint
	}
	
	public void tilepaint(int x, int y, int xend, int yend) //group painting
	{
		tiletopaint = tileset.getSubImage(x, yend); //currently selected tile from the TS. TS calls this so the BE knows which tile of the mutually loaded spritesheet to paint
	}
	
	
	@Override
	public void mousePressed(int button, int x, int y)// TODO: if == 0 can't subtract 1
	{ //button = 0 for click, 1 for right click
		x= (int)(((x-1)/this.tilewidth)*this.tilewidth); //convert to tile based coords
		y= (int)(((y-1)/this.tileheight)*this.tileheight);
		
		if(this.lshift) //if just the left shift is being pushed, paint collidables, if both left shift and ctrl, left click is begin right is end
		{
			if(this.lctrl) //lshift and lctrl are being pressed
			{
				if(button == 0)// click
				{
					if(!end.equals(new Point(x, y)))//if it is not set to the end
					begin = new Point(x, y);
				}
				if(button == 1)//right click
				{
					if(!begin.equals(new Point(x, y)))//if it is not set to the beginning
					end = new Point(x, y);
				}
			}
			else //left ctrl not being pushed, so paint collidables
			{
				if(!this.collidables.contains(new Point(x, y))) //if this tile is not already in the vector as collidable
				{
					collidables.add(new Point(x, y));
				}
			}
		}
		else //left shift not being pushed
		{
			if(this.lctrl) //just lctrl is being pushed, paint FX
			{
				
			}
			else //it is not. normal paint
			{
				paintlist.put(new Point(x, y), tiletopaint); //adds value to tile selection hashmap
			}
		}

	}
	
	@Override
	public void mouseDragged(int oldx, int oldy, int newx, int newy) //same as mousePressed. enables smoother painting by just dragging
	{
		this.mousePressed(1, newx, newy);
	}
	
	@Override
	public void keyPressed(int key, char c)
	{
		if(key == Input.KEY_LSHIFT)
		{
			this.lshift = true;
		}	
		
		if(key == Input.KEY_LCONTROL)
		{
			this.lctrl = true;
		}	
		
		if(key == Input.KEY_S)
		{
			this.skey = true;
		}
			
	}
	
	@Override
	public void keyReleased(int key, char c)
	{
		if(key == Input.KEY_LSHIFT)
		{
			this.lshift = false;
		}
		if(key == Input.KEY_LCONTROL)
		{
			this.lctrl = false;
		}	
		
		if(key == Input.KEY_S)
		{
			this.skey = false;
		}
			
	}

	@Override
	public boolean closeRequested() 
	{
		return true;
	}


	@Override
	public void init(GameContainer arg0) throws SlickException 
	{		

		try 
		{ //this is the shared tileset, just so it can load the tiles directly from its own reference to the same file.
		tileset = new SpriteSheet(tilesetfile, this.tilewidth, this.tileheight); 
		this.filewidth = tileset.getWidth();
		this.fileheight = tileset.getHeight();
		} 
		catch (SlickException e) 
		{
		System.err.println("BE: Error creating spritesheet from file. See stack trace: ");
		e.printStackTrace();
		}
		
		try
		{
		loadedimage = new Image("resources/BlankCanvas.png"); //TODO: add choice for user to load an initial image to paint on, other the black provided
		}
		catch(SlickException e)
		{
			System.err.println("Error loading initial file. wrong filename/ format? see stack trace: ");
			e.printStackTrace();
		}
		
		imagewithgrid = new Image(tileset.getWidth(), tileset.getHeight()); //will create this image from the user loaded base image (the one they want to paint on, if not blank)
		

			tiletopaint = new Image(this.tilewidth, this.tileheight);
		
			int filetilewidth = this.filewidth/this.tilewidth;
			int filetileheight = this.fileheight/this.tileheight;
			int totaltilecount = filetilewidth*filetileheight;
		
			paintlist = new HashMap<Point, Image>(totaltilecount); //hashmap to store painted tiles and locations
			tilestopaint = new HashMap<Point, Image>((totaltilecount/30)+1);
			collidables = new Vector<Point>(totaltilecount/2);
			//this.FX = new HashMap<Point, FX>();
			begin = null;
			end = null;
	}


	@Override
	public void render(GameContainer arg0, Graphics graphics) throws SlickException 
	{
		if(doOnce == 0) //so that the grid is only painted one time and reused. cuts down on rendering.
		{
			graphics.drawImage(loadedimage, 0, 0); //draws initial image 
			

			
			graphics.setColor(Color.orange); //sets the color to orange to generate the grid
			for(int i = 0; i<(this.filewidth/this.tilewidth); i++) //draw grid piece by piece
			{
				for(int j =0; j<(this.fileheight/this.tileheight); j++)
				graphics.drawRect(i*this.tilewidth, j*this.tileheight, this.tilewidth, this.tileheight);
			} 
			doOnce = 1;	
		graphics.copyArea(imagewithgrid, 0, 0); //copies the generated file to static image.
		}//end of doOnce
		
		
		
		graphics.drawImage(imagewithgrid, 0, 0); //simply prints the static image repeatedly instead of regenerating grid each time.
		for(Point coords : paintlist.keySet())//for each coordinate entry listed in the hashmap, 
		{
			graphics.drawImage(paintlist.get(coords), coords.x, coords.y); //paint the image assigned to those coordinates in their appropriate spot
		}
		graphics.setColor(Color.red);
		for(Point coords : collidables)//for each Point in collidables
		{	//Paint red rectangle to indicate collidable status
			graphics.drawRect(coords.x, coords.y, this.tilewidth, this.tileheight);
		}
		
		if(begin != null)
		{
			graphics.setColor(Color.green);
			graphics.drawRect(begin.x, begin.y, this.tilewidth, this.tileheight);
		}
		if(end != null)
		{
			graphics.setColor(Color.gray);
			graphics.drawRect(end.x, end.y, this.tilewidth, this.tileheight);
		}
		
		if(this.lctrl && this.lshift && this.skey) //save
		{
			graphics.drawImage(loadedimage, 0, 0);
			for(Point coords : paintlist.keySet())//for each coordinate entry listed in the hashmap, 
			{
				graphics.drawImage(paintlist.get(coords), coords.x, coords.y); //paint the image assigned to those coordinates in their appropriate spot
			}
			
			Image img = new Image(this.filewidth, this.fileheight);
			graphics.copyArea(img, 0, 0);
			Level write = new Level(img, this.begin, this.end, "Test");
			
			write.setCollide(this.collidables);
			Level.writeOut(write);
			System.exit(1);
		}
		
	}


	@Override
	public void update(GameContainer arg0, int arg1) throws SlickException 
	{
		
	}
	
	protected void setTileSize(int x, int y)
	{
		this.tilewidth = x;
		this.tileheight = y;
	}
	
}//CLASS END
